﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Composition;
using BTGICS.CommonLibrary;

namespace BTGICS.Hammurabi
{
    [Export( typeof( IPlugIn ) )]
    public class PlugIn : IPlugIn
    {
        #region Private Properties
        private int Year = 0;
        private int Population = 0;
        private int NumberOfAcresOwned = 0;
        private int NumberOfBushelsInStore = 0;
        private int NumberOfBushelsHarvested = 0;
        private int NumberOfBushelsRatsAte = 0;
        private int NumberOfBushelsHarvestedPerAcre = 0;
        private int NumberOfAcresToPlantWithSeed = 0;
        private int NumberOfImmigrants = 0;
        private int QuestionAnswer = 0;
        private int NumberOfPeopleThatStarved = 0;
        private int LandIsTradingAt = 0;
        private bool PlagueStruck = false;
        private int NumberOfBushelsToFeedPeople = 0;
        private int NumberOfPeopleWithFullTummies = 0;
        private float NumberOfDeaths = 0.0f;
        private float PercentageOfPopulationStarving = 0.0f;
        private Random Rnd = new Random();
        private bool GameIsOver = false;
        private int CalculationDelta
        {
            get
            {
                return  Rnd.Next( 10 ) + 1;
            }
        }
        #endregion
        #region IPlugIn Members

        public string Name
        {
            get
            {
                return "Hammurabi";
            }
        }

        public string Description
        {
            get
            {
                return "Try your hand at governing Ancient Sumeria successfully for a 10 year\r\n\tterm of office.";
            }
        }


        public void Run()
        {
            Console.ResetColor();
            Console.Clear();
            Population = 95;
            NumberOfBushelsInStore = 2800;
            NumberOfBushelsHarvested = 3000;
            NumberOfBushelsRatsAte = NumberOfBushelsHarvested - NumberOfBushelsInStore;
            NumberOfBushelsHarvestedPerAcre = 3;
            NumberOfAcresOwned = NumberOfBushelsHarvested / NumberOfBushelsHarvestedPerAcre;
            NumberOfImmigrants = 5;

            while( !GameIsOver )
            {
                Year++;
                if( Year < 11 )
                {
                    EndOfYearReport();
                    if( !GameIsOver )
                        BuyLand();
                    if( !GameIsOver )
                        SellLand();
                    if( !GameIsOver )
                        FeedThePeople();
                    if( !GameIsOver )
                        PlantSeed();
                    if( !GameIsOver )
                        EndOfYearEvents();
                }
                else
                {
                    Console.Clear();
                    Console.BackgroundColor = ConsoleColor.White;
                    Console.ForegroundColor = ConsoleColor.DarkBlue;
                    Console.WriteLine( "HAMMURABI                                                        YEAR:{0}".PadRight( 79, ' ' ), Year );
                    Console.ResetColor();
                    Console.WriteLine( "In your 10-year term of office,\r\n\t{0}% of the population starved per year on average.", PercentageOfPopulationStarving/10);
                    Console.WriteLine( "\tA total of {0} {1} died!", NumberOfDeaths, NumberOfDeaths == 1 ? "person" : "people" );
                    int land = NumberOfAcresOwned / Population;
                    Console.WriteLine( "You started with 10 acres per person and ended with {0} acre{1}per person.", land, land == 1 ? " " : "s " );
                    if( PercentageOfPopulationStarving > 33f || land < 7 )
                    {
                        Impeachment();
                    }
                    else if( PercentageOfPopulationStarving > 10 || land < 9 )
                    {
                        SmacksOfNero();
                    }
                    else if( PercentageOfPopulationStarving > 3 || land < 10 )
                    {
                        WasntTooBad();
                    }
                    else
                    {
                        FantasticPerformance();
                    }
                }
            }
            Console.WriteLine( "So long for now" );
        }

        #endregion
        #region End Of Year Events
        private void EndOfYearEvents()
        {
            // a bountiful harvest
            NumberOfBushelsHarvestedPerAcre = CalculationDelta;
            NumberOfBushelsHarvested = NumberOfAcresToPlantWithSeed * NumberOfBushelsHarvestedPerAcre;
            NumberOfBushelsRatsAte = 0;
            if( CalculationDelta == CalculationDelta )
            {
                // rats are running wild
                NumberOfBushelsRatsAte = NumberOfBushelsInStore / CalculationDelta;
            }
            NumberOfBushelsInStore -= NumberOfBushelsRatsAte;
            NumberOfBushelsInStore += NumberOfBushelsHarvested;
            // let's have some babies / new citizens
            NumberOfImmigrants = CalculationDelta * ( ( 20 * NumberOfAcresOwned + NumberOfBushelsInStore ) / Population / 100 ) + 1;
            // how many people had full tummies?
            NumberOfPeopleWithFullTummies = NumberOfBushelsToFeedPeople / 20;
            // horrors, a 15% change of plague
            PlagueStruck = Rnd.Next(100) < 16;
            // starve enough people for impeachment?
            if( Population < NumberOfPeopleWithFullTummies )
            {
                NumberOfPeopleThatStarved = 0;
            }
            else
            {
                NumberOfPeopleThatStarved = Population - NumberOfPeopleWithFullTummies;
                PercentageOfPopulationStarving = (int)((float)(((float)NumberOfPeopleThatStarved / (float)Population)/(float)Year) * 100);
                Population = NumberOfPeopleWithFullTummies;
                NumberOfDeaths += NumberOfPeopleThatStarved;
            }
        }
        #endregion
        #region Horrible Plague
        private void HorriblePlague()
        {
            Console.WriteLine( "A HORRIBLE Plague Struck!  Half of the people died." );
            Population /= 2;
        }
        #endregion
        #region End Of Year Report
        private void EndOfYearReport()
        {
            if( ( float ) NumberOfPeopleThatStarved > ( 0.45 * ( float ) Population ) )
            {
                Impeachment();
            }
            else
            {
                Console.Clear();
                Console.BackgroundColor = ConsoleColor.White;
                Console.ForegroundColor = ConsoleColor.DarkBlue;
                Console.WriteLine( "HAMMURABI                                                        YEAR:{0}".PadRight(79,' '), Year );
                Console.ResetColor();
                Console.WriteLine( "Hammurabi, I beg to report to you, in the year {0}, {1} {3} starved,\r\n{2}, came to the city.",
                    Year, NumberOfPeopleThatStarved, NumberOfImmigrants, NumberOfPeopleThatStarved == 1 ? "person" : "people" );
                Population += NumberOfImmigrants;
                if( PlagueStruck )
                {
                    HorriblePlague();
                }
                Console.WriteLine( "The population is now {0}", Population );
                Console.WriteLine( "The city now owns {0} acres of land.", NumberOfAcresOwned );
                Console.WriteLine( "You harvested {0} bushel{1}per acre.", NumberOfBushelsHarvestedPerAcre, NumberOfBushelsHarvestedPerAcre  == 1 ? " " : "s " );
                Console.WriteLine( "You harvested a total of {0} bushel{1}.", NumberOfBushelsHarvested, NumberOfBushelsHarvested == 1 ? "" : "s " );
                Console.WriteLine( "Rates ate {0} bushel{1}.", NumberOfBushelsRatsAte, NumberOfBushelsRatsAte == 1 ? "" : "s" );
                Console.WriteLine( "You now have {0} bushel{1}in store.\r\n", NumberOfBushelsInStore, NumberOfBushelsInStore == 1 ? " " : "s " );
                Console.WriteLine( "-".PadRight( 79, '-' ) );
            }
        }
        #endregion
        #region Game Endings
        #region Smacks Of Nero
        private void SmacksOfNero()
        {
            Console.WriteLine( "-".PadRight( 79, '-' ) );
            GameIsOver = true;
            Console.WriteLine( "Your heavy-handed performance smacks of Nero and Ivan IV." );
            Console.WriteLine( "The people (remaining) find you an unpleasant ruler, and frankly, hate your guts!" );
            Console.WriteLine( "-".PadRight( 79, '-' ) );
        }
        #endregion
        #region Wasn't Too Bad
        private void WasntTooBad()
        {
            Console.WriteLine( "-".PadRight( 79, '-' ) );
            GameIsOver = true;
            Console.WriteLine( "Your performance could have been somewhat better, but really wasn't too bad at\r\nall. " );
            int wanttoassassinate = ( int ) ( ( ( float ) Population * .08 ) * ( float ) Rnd.Next( 1 ) );
            Console.WriteLine( "{0} people would dearly like to see you assassinated,\r\nbut we all have our trivial problems.", wanttoassassinate );
            Console.WriteLine( "-".PadRight( 79, '-' ) );
        }
        #endregion
        #region Fanstastic Performance
        private void FantasticPerformance()
        {
            Console.WriteLine( "-".PadRight( 79, '-' ) );
            GameIsOver = true;
            Console.WriteLine( "A fantastic performance!!!  Sargon, Gilgamesh, and Ashurbanipal combined\r\ncould not have done better!" );
            Console.WriteLine( "-".PadRight( 79, '-' ) );
        }
        #endregion
        #region Impeachment
        private void Impeachment()
        {
            Console.WriteLine( "-".PadRight( 79, '-' ) );
            GameIsOver = true;
            Console.WriteLine( "You starved {0} people in one year!!!", NumberOfPeopleThatStarved );
            Console.WriteLine( "Due to this extreme mismanagement you have not only been impeached and thrown\r\nout of office but you have also been declared \"National Fink\"!!" );
            Console.WriteLine( "-".PadRight( 79, '-' ) );
        }
        #endregion
        #endregion
        #region I Cannot Do It
        private void ICannotDoIt()
        {
            Console.WriteLine( "Hammurabi, I cannot do what you wish.\r\nGet yourself another steward!!!!!" );
        }
        #endregion
        #region Get Input
        private int GetInput()
        {
            while( true )
            {
                Console.ForegroundColor = ConsoleColor.Green;
                string ans = Console.ReadLine();
                Console.ResetColor();
                try
                {
                    return int.Parse( ans );
                }
                catch
                {
                    switch( Rnd.Next( 5 ) )
                    {
                        case 0:
                            Console.WriteLine( "Hammurabi, Have you been fermenting the grains?" );
                            break;
                        case 1:
                            Console.WriteLine( "Hammurabi, I do not understand." );
                            break;
                        case 2:
                            Console.WriteLine( "Hammurabi, I do not think that is a number." );
                            break;
                        case 3:
                            Console.WriteLine( "Hammurabi, Your humble servant is confused." );
                            break;
                        case 4:
                            Console.WriteLine( "Hammurabi, I beg you to answer sensibly." );
                            break;
                    }
                }
            }

        }
        #endregion
        #region Buy Land
        private void BuyLand()
        {
            LandIsTradingAt = CalculationDelta + 17;
            Console.WriteLine( "Land is trading at {0} bushels per acre.", LandIsTradingAt );
            Console.WriteLine( "How many acres do you wish to buy?" );
            while( true )
            {
                QuestionAnswer = GetInput();
                if( QuestionAnswer > -1 )
                {
                    if( ( LandIsTradingAt * QuestionAnswer ) > NumberOfBushelsInStore )
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only {0} bushel{1}of grain.  Now then,", NumberOfBushelsInStore, NumberOfBushelsInStore == 1 ? "" : "s " );
                    }
                    else
                    {
                        NumberOfAcresOwned += QuestionAnswer;
                        NumberOfBushelsInStore -= ( LandIsTradingAt * QuestionAnswer );
                        break;
                    }
                }
                else
                {
                    ICannotDoIt();
                    GameIsOver = true;
                    break;
                }
            }
        }
        #endregion
        #region Sell Land
        private void SellLand()
        {
            Console.WriteLine( "How many acres do you wish to sell?" );
            while( true )
            {
                QuestionAnswer = GetInput();
                if( QuestionAnswer > -1 )
                {
                    if( QuestionAnswer > NumberOfAcresOwned )
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only own {0} acre{1}of land.  Now then,", NumberOfBushelsInStore, NumberOfBushelsInStore == 1 ? "" : "s " );
                    }
                    else
                    {
                        NumberOfAcresOwned -= QuestionAnswer;
                        NumberOfBushelsInStore += ( LandIsTradingAt * QuestionAnswer );
                        break;
                    }
                }
                else
                {
                    ICannotDoIt();
                    GameIsOver = true;
                    break;
                }
            }
        }
        #endregion
        #region Feed The People
        private void FeedThePeople()
        {
            Console.WriteLine( "How many bushels do you wish to feed your people?" );
            while( true )
            {
                QuestionAnswer = GetInput();
                if( QuestionAnswer > -1 )
                {
                    if( QuestionAnswer > NumberOfBushelsInStore )
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only {0} bushel{1}of grain.  Now then,", NumberOfBushelsInStore, NumberOfBushelsInStore == 1 ? "" : "s " );
                    }
                    else
                    {
                        NumberOfBushelsInStore -= QuestionAnswer;
                        NumberOfBushelsToFeedPeople = QuestionAnswer;
                        break;
                    }
                }
                else
                {
                    ICannotDoIt();
                    GameIsOver = true;
                    break;
                }
            }
        }
        #endregion
        #region Plant Seed
        private void PlantSeed()
        {
            Console.WriteLine( "How many acres do you wish to plant with seed?" );
            while( true )
            {
                QuestionAnswer = GetInput();
                if( QuestionAnswer > -1 )
                {
                    // trying to plant more acres than you own?
                    if( QuestionAnswer > NumberOfAcresOwned )
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only own {0} acre{1}of land.  Now then,", NumberOfAcresOwned, NumberOfAcresOwned == 1 ? " " : "s " );
                    }
                        // enough grain for seed?
                    else if((QuestionAnswer / 2) > NumberOfBushelsInStore)
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only {0} bushel{1}of grain.  Now then,", NumberOfBushelsInStore, NumberOfBushelsInStore == 1 ? " " : "s " );
                    }
                        // enough people to tend the crops?
                    else if( QuestionAnswer > ( 10 * Population ) )
                    {
                        Console.WriteLine( "Hammurabi, think again.  You have only {0} {1} to tend the fields.  Now then,", Population, Population == 1 ? "person" : "people" );
                    }
                    else
                    {
                        NumberOfBushelsInStore -= (QuestionAnswer / 2);
                        NumberOfAcresToPlantWithSeed = QuestionAnswer;
                        break;
                    }
                }
                else
                {
                    ICannotDoIt();
                    GameIsOver = true;
                    break;
                }
            }

        }
        #endregion
    }
}
